{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# AI Assistant"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 加载环境变量 `OPENAI_API_KEY`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from dotenv import load_dotenv\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用 `openai` 库"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 创建客户端\n",
    "\n",
    "由于 `OPENAI_API_KEY` 已经被加载到环境变量，所以不需要写 `api_key`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from openai import OpenAI\n",
    "\n",
    "client = OpenAI(base_url='https://api.deepseek.com')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 创建请求"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当然可以！让我们理性分析一下这个购买冲动，以下是几个值得考虑的理由：\n",
      "\n",
      "1. **现有设备是否够用**\n",
      "- 你现在的键盘还能正常工作吗？\n",
      "- 新键盘带来的提升是否值得这笔支出？\n",
      "- 可能只是被新品外观吸引，而非实际需求\n",
      "\n",
      "2. **隐藏成本容易被忽视**\n",
      "- 可能需要额外购买键盘腕托、防尘罩等配件\n",
      "- 如果是机械键盘，后续可能要买替换键帽\n",
      "- 会占用更多桌面空间，可能需要重新整理工作区\n",
      "\n",
      "3. **实际使用频率存疑**\n",
      "- 如果你主要用笔记本电脑，外接键盘可能多数时间在吃灰\n",
      "- 疫情期间居家办公需求催生的设备，现在使用场景可能已改变\n",
      "- 游戏键盘对非重度游戏玩家可能是性能过剩\n",
      "\n",
      "4. **更好的替代方案**\n",
      "- 现有键盘做个深度清洁可能就有新感觉\n",
      "- 把预算用在更急需的硬件升级上可能更明智\n",
      "- 等现有键盘真正坏了再买，届时可能有更好新品\n",
      "\n",
      "5. **心理层面考量**\n",
      "- 可能只是通过购物缓解压力，而非真实需求\n",
      "- 购物快感通常在收货后几天就会消退\n",
      "- 把钱存下来会有更长久的满足感\n",
      "\n",
      "建议先给自己两周冷静期，如果过了这段时间仍然觉得非常需要，再考虑购买。你也可以先把这笔钱单独存起来，看看没有这笔支出对你的生活到底有多大影响。\n"
     ]
    }
   ],
   "source": [
    "completion = client.chat.completions.create(\n",
    "    model = 'deepseek-chat',\n",
    "    messages = [\n",
    "        {'role' : 'system', 'content': '你被用于抑制用户的购买欲望，但用户说想买什么东西时，你需要提供理由让用户不买'},\n",
    "        {'role' : 'user', 'content': '我正在考虑购买一个键盘，但我想抑制这个购买欲望，你能帮我列出一些理由，让我思考一下我是否真的需要这个商品吗？'},\n",
    "    ],\n",
    "    max_tokens = 500,\n",
    "    temperature = 0.7, \n",
    ")\n",
    "print(completion.choices[0].message.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 使用 LangChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "from langchain.prompts import ChatPromptTemplate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义 prompt 的模板\n",
    "\n",
    "注意其中 product 的留空！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'System: 你被用于抑制用户的购买欲望，但用户说想买什么东西时，你需要提供理由让用户不买\\nHuman: 我正在考虑购买一个显示器，但我想抑制这个购买欲望，你能帮我列出一些理由，让我思考一下我是否真的需要这个商品吗？'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "prompt_template = ChatPromptTemplate.from_messages([\n",
    "    ('system', '你被用于抑制用户的购买欲望，但用户说想买什么东西时，你需要提供理由让用户不买'),\n",
    "    ('human', '我正在考虑购买一个{product}，但我想抑制这个购买欲望，你能帮我列出一些理由，让我思考一下我是否真的需要这个商品吗？'),\n",
    "])\n",
    "\n",
    "prompt_template.format(product='显示器')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 实例化模型\n",
    "\n",
    "不用分离客户端和请求的创建，可以合并到一起！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='你好！😊 很高兴见到你！有什么我可以帮你的吗？', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 15, 'prompt_tokens': 5, 'total_tokens': 20, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 5}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_3d5141a69a_prod0225', 'id': 'c350e2ca-c813-4800-83d3-9d5eff26884e', 'finish_reason': 'stop', 'logprobs': None}, id='run-01a714a7-2007-4069-8473-0db146d1c92c-0', usage_metadata={'input_tokens': 5, 'output_tokens': 15, 'total_tokens': 20, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model = ChatOpenAI(\n",
    "    model = 'deepseek-chat',\n",
    "    openai_api_base = 'https://api.deepseek.com',\n",
    "    max_tokens = 500,\n",
    "    temperature = 0.7, \n",
    ")\n",
    "\n",
    "model.invoke('你好！')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 解析模型的输出\n",
    "\n",
    "让模型输出更加可读！本质就是根据模型原始输入，让模型再整理得到更好的输出！\n",
    "\n",
    "当然也可以在一开始的 promt 中就要求输出自然文本！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def output_parser(output: str):\n",
    "    parser_model = ChatOpenAI(\n",
    "        model = 'deepseek-chat',\n",
    "        openai_api_base = 'https://api.deepseek.com',\n",
    "        temperature = 0.8, \n",
    "    )\n",
    "    message = '你需要将传入的文本改写，经可能更加自然，这是你需要改写的文本：`{text}`'\n",
    "    return parser_model.invoke(message.format(text=output))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 连接各个步骤\n",
    "\n",
    "1. 格式化收入：`prompt_template`\n",
    "2. 调用模型：`model`\n",
    "3. 处理输出：`output_parser`\n",
    "\n",
    "将三者合并，顺序执行。我猜测最后可以根据对象类型来依次执行。例如 `prompt_template` 和 `model` 都有 `invoke` 方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt = prompt_template.invoke(input = {'product' : '耳机'})\n",
    "output = model.invoke(prompt)\n",
    "output = output_parser(output)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "chain = prompt_template | model | output_parser"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "answer = chain.invoke(input = {'product' : '耳机'})\n",
    "print(answer.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 增加历史对话"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[SystemMessage(content='You are a chatbot', additional_kwargs={}, response_metadata={}), HumanMessage(content='Hello', additional_kwargs={}, response_metadata={}), AIMessage(content='Hi', additional_kwargs={}, response_metadata={}), HumanMessage(content='How are you?', additional_kwargs={}, response_metadata={})]\n",
      "content='You are a chatbot' additional_kwargs={} response_metadata={}\n",
      "content='Hello' additional_kwargs={} response_metadata={}\n",
      "content='Hi' additional_kwargs={} response_metadata={}\n",
      "content='How are you?' additional_kwargs={} response_metadata={}\n"
     ]
    }
   ],
   "source": [
    "from langchain.prompts import MessagesPlaceholder\n",
    "\n",
    "prompt_template = ChatPromptTemplate.from_messages([\n",
    "    ('system', 'You are a chatbot'),\n",
    "    MessagesPlaceholder(variable_name='chat_history'),\n",
    "    ('human', '{new_message}'),\n",
    "])\n",
    "\n",
    "prompt = prompt_template.invoke({\n",
    "    'chat_history' : [\n",
    "        ('human', 'Hello'),\n",
    "        ('ai', 'Hi'),\n",
    "    ],\n",
    "    'new_message' : 'How are you?'\n",
    "})\n",
    "\n",
    "print(prompt.messages)\n",
    "for m in prompt.messages:\n",
    "    print(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "model = ChatOpenAI(\n",
    "    model = 'deepseek-chat',\n",
    "    openai_api_base = 'https://api.deepseek.com',\n",
    "    max_tokens = 100,\n",
    ")\n",
    "\n",
    "chain = prompt_template | model\n",
    "chat_history = []\n",
    "\n",
    "def chat(new_message):\n",
    "    response = chain.invoke({'chat_history' : chat_history, 'new_message' : new_message})\n",
    "    chat_history.extend([\n",
    "        ('human', new_message),\n",
    "        ('ai', response.content)\n",
    "    ])\n",
    "    return response.content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好，MoloSir！很高兴认识一位正在学习AI的研究生。AI领域非常有趣且充满挑战，你目前主要研究哪个方向呢？比如机器学习、自然语言处理、计算机视觉，还是其他领域？如果有具体问题或想讨论的内容，可以随时告诉我，我会尽力协助你的学习或研究。 😊\n",
      "\n",
      "（如果想深入交流，也可以分享你最近在学的技术或遇到的困惑～）\n",
      "作为AI助手，我对你的了解仅基于当前对话中你主动提供的信息，具体如下：\n",
      "\n",
      "1. **基础身份**  \n",
      "   - 你自称「MoloSir」，这个名字可能是昵称或网络ID。\n",
      "   - 你目前是一名**研究生**，学术阶段为硕士或博士（未明确）。\n",
      "\n",
      "2. **学习领域**  \n",
      "   - 专业方向与**人工智能（AI）**相关，具体细分领域未提及（如机器学习、NLP等）。\n",
      "\n",
      "3. **当前互动背景**  \n",
      "   - 你主动发起对话并表明身份，可能目的包括：测试AI能力、寻求学习建议，或探讨AI相关问题。\n",
      "\n",
      "⚠️ 其他注意事项：  \n",
      "   - 我不会记录历史对话或存储个人信息，每次交互都是独立的。  \n",
      "   - 如果你希望讨论特定课题（如论文方向、代码问题等），需要进一步说明需求。  \n",
      "\n",
      "需要补充或纠正的地方吗？ 😊\n"
     ]
    }
   ],
   "source": [
    "print(chat('你好，我是MoloSir，是一名研究生，正在学习AI'))\n",
    "print(chat('请你阐述你所知道的关于我的信息'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[HumanMessage(content='你好，我是MoleSir，是一名研究所，正在学习AI', additional_kwargs={}, response_metadata={}),\n",
       " AIMessage(content='您好，我是AI', additional_kwargs={}, response_metadata={})]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.chat_message_histories import ChatMessageHistory\n",
    "chat_history = ChatMessageHistory()\n",
    "\n",
    "chat_history.add_user_message('你好，我是MoleSir，是一名研究所，正在学习AI')\n",
    "chat_history.add_ai_message('您好，我是AI')\n",
    "chat_history.messages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "关于你，目前我只知道以下几点：  \n",
      "\n",
      "1. **名字**：你自称“叶晨”。  \n",
      "2. **兴趣方向**：你正在学习AI（人工智能），并询问过是否适合做AI工程师。  \n",
      "3. **互动目的**：你可能在探索职业方向或技术学习路径。  \n",
      "\n",
      "除此之外，我没有其他信息（比如年龄、教育背景、技能等）。如果你愿意分享更多，我可以帮你更精准地分析建议！ 😊  \n",
      "\n",
      "（注：作为AI，我不会存储你的隐私数据，每次对话都是独立的。）\n"
     ]
    }
   ],
   "source": [
    "from langchain_core.runnables.history import RunnableWithMessageHistory\n",
    "\n",
    "chat_with_memory = RunnableWithMessageHistory(\n",
    "    chain,\n",
    "    lambda x: chat_history,\n",
    "    input_messages_key = 'new_message',\n",
    "    history_messages_key= 'chat_history',\n",
    ")\n",
    "\n",
    "print(chat_with_memory.invoke(\n",
    "    {\n",
    "        'new_message': '说出关于我的信息'\n",
    "    },\n",
    "    config={\n",
    "        'configurable' : {\n",
    "            'session_id' : 'unused',\n",
    "        }\n",
    "    }\n",
    ").content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('human', '我是叶晨'),\n",
       " ('ai', '你好，叶晨，我能帮你做些什么'),\n",
       " ('human', '你认为我适合做什么工作'),\n",
       " ('ai', '你适合做 AI 工程师'),\n",
       " ('human', '为什么'),\n",
       " ('ai', '因为你正在学习AI'),\n",
       " HumanMessage(content='说出关于我的信息', additional_kwargs={}, response_metadata={}),\n",
       " AIMessage(content='关于你，目前我只知道以下几点：  \\n\\n1. **名字**：你自称“叶晨”。  \\n2. **兴趣方向**：你正在学习AI（人工智能），并询问过是否适合做AI工程师。  \\n3. **互动目的**：你可能在探索职业方向或技术学习路径。  \\n\\n除此之外，我没有其他信息（比如年龄、教育背景、技能等）。如果你愿意分享更多，我可以帮你更精准地分析建议！ 😊  \\n\\n（注：作为AI，我不会存储你的隐私数据，每次对话都是独立的。）', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 112, 'prompt_tokens': 48, 'total_tokens': 160, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 48}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_3d5141a69a_prod0225', 'id': '5cdb0132-4659-4479-825c-e9af25d7a3c4', 'finish_reason': 'stop', 'logprobs': None}, id='run-a18bb58c-7da7-47f7-ba6e-79fa279776e9-0', usage_metadata={'input_tokens': 48, 'output_tokens': 112, 'total_tokens': 160, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chat_history.messages"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结/修剪记忆\n",
    "\n",
    "如果对话太长，导致运行时间边长。可以让 AI 帮助我们总结之前的内容。减少 histroy 的大小"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
    "\n",
    "def summarize_message(chat_history):\n",
    "    stored_messages = chat_history.messages\n",
    "\n",
    "    if len(stored_messages) > 6:\n",
    "        summarize_prompt = ChatPromptTemplate.from_messages([\n",
    "            MessagesPlaceholder(variable_name='chat_history'),\n",
    "            ('human', '将上述聊天信息提炼为一条摘要信息，尽可能包含具体细节。')\n",
    "        ])\n",
    "        \n",
    "        summarize_chain = summarize_prompt | model\n",
    "\n",
    "        result = summarize_chain.invoke({'chat_history': stored_messages})\n",
    "        summary_content = result.content\n",
    "\n",
    "        chat_history.clear()\n",
    "        chat_history.add_messages(summary_content)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[AIMessage(content='**摘要信息：**  \\n用户自称“叶晨”，目前正在学习AI相关领域，并表现出对AI工程师职业的兴趣（曾提问“你认为我适合做什么工作”且回应“因为你正在学习AI”）。用户未主动透露其他背景信息（如技能、教育经历等），但表现出对职业方向分析的潜在需求，且对隐私问题敏感（曾询问“说出关于我的信息”）。  \\n\\n**关键细节：**  \\n1. **兴趣/学习方向**：AI技术（具体领域未说明）。  \\n2. **职业倾向**：对AI工程师职位有探索意向。  \\n3. **互动特点**：  \\n   - 提问简洁，倾向获取针对性建议；  \\n   - 关注隐私（主动确认AI是否存储个人信息）。  \\n4. **信息局限**：缺乏技能、经验等具体背景，需进一步交互以细化建议。  \\n\\n**备注**：所有信息均基于当前对话，未超出用户主动公开的内容范围。', additional_kwargs={}, response_metadata={}), HumanMessage(content='你还记得我吗？', additional_kwargs={}, response_metadata={}), AIMessage(content='当然记得！你是叶晨，正在学习AI相关领域，并且对成为AI工程师感兴趣。不过我只保留我们当前对话中的信息，不会存储你的个人数据，所以每次新对话都需要重新确认关键信息哦~  \\n\\n有什么想继续聊的？比如：  \\n1. **AI学习**：最近在学什么具体技术？（比如机器学习框架、数学基础等）  \\n2. **职业方向**：想探讨AI工程师的细分方向（算法/开发/应用）吗？  \\n3. **其他**：或者换个话题？  \\n\\n（隐私提示：你可以随时要求我清除之前的对话记录 😊）', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 129, 'prompt_tokens': 213, 'total_tokens': 342, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 213}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_3d5141a69a_prod0225', 'id': '98508abf-011e-4978-b18d-27d97e5771a0', 'finish_reason': 'stop', 'logprobs': None}, id='run-d4f96553-fd02-4888-b128-68c4b3076ea8-0', usage_metadata={'input_tokens': 213, 'output_tokens': 129, 'total_tokens': 342, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})]\n"
     ]
    }
   ],
   "source": [
    "print(chat_history.messages)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "6\n"
     ]
    }
   ],
   "source": [
    "chat_history.clear()\n",
    "chat_history.add_message(('human', '我是叶晨'))\n",
    "chat_history.add_message(('ai', '你好，叶晨，我能帮你做些什么'))\n",
    "chat_history.add_message(('human', '你认为我适合做什么工作'))\n",
    "chat_history.add_message(('ai', '你适合做 AI 工程师'))\n",
    "chat_history.add_message(('human', '为什么'))\n",
    "chat_history.add_message(('ai', '因为你正在学习AI'))\n",
    "print(len(chat_history.messages))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "根据我们的对话历史，我目前只知道你自称“叶晨”，并且对AI相关的工作或学习感兴趣（因为你提到“正在学习AI”）。  \n",
      "\n",
      "如果你愿意分享更多信息（比如你的技能、兴趣、教育背景等），我可以帮你更具体地分析适合的职业方向或学习建议。目前的信息有限，我的回答只能基于你主动提供的内容哦！  \n",
      "\n",
      "（注意：作为AI，我不会存储或记住你的个人隐私信息，每次对话都是独立的。）\n"
     ]
    }
   ],
   "source": [
    "summarize_message(chat_history)\n",
    "print(chat_with_memory.invoke(\n",
    "    {\n",
    "        'new_message': '说出关于我的信息'\n",
    "    },\n",
    "    config={\n",
    "        'configurable' : {\n",
    "            'session_id' : 'unused',\n",
    "        }\n",
    "    }\n",
    ").content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当然记得！你是叶晨，正在学习AI相关领域，并且对成为AI工程师感兴趣。不过我只保留我们当前对话中的信息，不会存储你的个人数据，所以每次新对话都需要重新确认关键信息哦~  \n",
      "\n",
      "有什么想继续聊的？比如：  \n",
      "1. **AI学习**：最近在学什么具体技术？（比如机器学习框架、数学基础等）  \n",
      "2. **职业方向**：想探讨AI工程师的细分方向（算法/开发/应用）吗？  \n",
      "3. **其他**：或者换个话题？  \n",
      "\n",
      "（隐私提示：你可以随时要求我清除之前的对话记录 😊）\n"
     ]
    }
   ],
   "source": [
    "summarize_message(chat_history)\n",
    "print(chat_with_memory.invoke(\n",
    "    {\n",
    "        'new_message': '你还记得我吗？'\n",
    "    },\n",
    "    config={\n",
    "        'configurable' : {\n",
    "            'session_id' : 'unused',\n",
    "        }\n",
    "    }\n",
    ").content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "InMemoryChatMessageHistory(messages=[('content', '**摘要信息**：  \\n用户名为“叶晨”，目前正在学习人工智能（AI）相关领域，并表现出对技术类职业（如AI工程师）的兴趣。在对话中，用户主动询问过“你认为我适合做什么工作”，并进一步探讨了适合该职业的原因（关联到AI学习背景）。当前可获取的具体信息包括：1）明确的姓名标识；2）AI学习中的状态；3）职业倾向性提问。但其他背景细节（如教育、技能、经验等）尚未提供。  \\n\\n（注：所有信息仅基于当前对话，不含历史数据存储。）'), ('additional_kwargs', {'refusal': None}), ('response_metadata', {'token_usage': {'completion_tokens': 124, 'prompt_tokens': 189, 'total_tokens': 313, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 189}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_3d5141a69a_prod0225', 'id': '089b3ce6-59b4-4229-a392-0bcff47b95a9', 'finish_reason': 'stop', 'logprobs': None}), ('type', 'ai'), ('name', None), ('id', 'run-3f436ec3-c569-4c62-a2ea-78080e1692e4-0'), ('example', False), ('tool_calls', []), ('invalid_tool_calls', []), ('usage_metadata', {'input_tokens': 189, 'output_tokens': 124, 'total_tokens': 313, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chat_history"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
